<template>
  <TransitionGroup v-bind="transitionProps" tag="ul" class="fa-drag-sort" :class="{ 'is-sortable': !disabled }">
    <slot />
  </TransitionGroup>
</template>

<script lang="ts">
import { computed, defineComponent, getCurrentInstance, PropType, provide, reactive, toRefs } from 'vue'

/** 拖拽排序 */
export default defineComponent({
  name: 'FaDragSort',

  props: {
    /** 需要排序的数据列表 */
    list: {
      type: Array,
      required: true
    },

    /** 过渡效果 */
    transition: {
      type: [String, Object] as PropType<
        string | { name: string; duration?: number; tag?: string; moveClass?: string }
      >,

      default: () => ({ name: 'fa-drag-sort-transition', duration: 300 })
    },

    /**
     * 拖拽句柄
     * 1. 如果类型为 boolean，`true` 则启用默认句柄，`false` 则整体拖拽不使用句柄
     * 2. 如果类型为 string，则通过选择器查找到的第一个元素为句柄
     */
    handle: {
      type: [Boolean, String],
      default: false
    },

    /** 是否禁用拖拽排序 */
    disabled: {
      type: Boolean,
      default: false
    }
  },

  emits: [
    /** 拖拽开始 `{ e: DragEvent, dragIndex: number, dragItem: unknown }` */
    'drag-start',
    /** 拖入 `{ e: DragEvent, dragIndex: number, dragItem: unknown, dropIndex: number, dropItem: unknown }` */
    'drop'
  ],

  setup(props) {
    provide('Dns', getCurrentInstance()?.proxy)

    /** 拖拽数据 */
    const state = reactive({
      /** 拖拽项索引 */
      activeIndex: -1,

      /** 拖拽经过索引 */
      overIndex: -1,

      /** 鼠标悬浮索引 */
      hoverIndex: -1
    })

    return {
      ...toRefs(state),

      /** 过渡选项 */
      transitionProps: computed(() => {
        const trans = props.transition
        const option = typeof trans === 'string' ? { name: trans } : trans

        return { duration: 300, ...option }
      })
    }
  }
})
</script>

<style lang="scss">
.fa-drag-sort {
  margin: 0;
  padding: 0;
}

.fa-drag-sort-transition {
  &-enter-active,
  &-leave-active {
    transition: all 0.3s ease-in-out;
  }

  &-enter,
  &-leave-to {
    transform: scale(0);
    opacity: 0;
  }
}
</style>
